blob: 700f6dda9988f23cc2639b0b06f3da254c396b20 [file] [log] [blame]
Andrea Campanella378e21a2017-06-07 12:09:59 +02001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Andrea Campanella378e21a2017-06-07 12:09:59 +02003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andrea Campanella0288c872017-08-07 18:32:51 +020017package org.onosproject.drivers.p4runtime;
Andrea Campanella378e21a2017-06-07 12:09:59 +020018
Carmelo Cascone080969a2019-08-27 16:06:55 -070019import org.onlab.packet.EthType;
20import org.onosproject.net.flow.instructions.Instructions;
Andrea Campanella378e21a2017-06-07 12:09:59 +020021import org.onosproject.net.packet.OutboundPacket;
22import org.onosproject.net.packet.PacketProgrammable;
Frank Wangc672c982017-07-18 16:09:28 +080023import org.onosproject.net.pi.model.PiPipelineInterpreter;
Frank Wangc672c982017-07-18 16:09:28 +080024
Carmelo Cascone080969a2019-08-27 16:06:55 -070025import java.nio.ByteBuffer;
26import java.util.stream.Collectors;
Andrea Campanella378e21a2017-06-07 12:09:59 +020027
Carmelo Casconec2be50a2019-04-10 00:15:39 -070028import static org.onosproject.drivers.p4runtime.P4RuntimeDriverUtils.getInterpreter;
Carmelo Cascone080969a2019-08-27 16:06:55 -070029import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
Carmelo Casconec2be50a2019-04-10 00:15:39 -070030
Andrea Campanella378e21a2017-06-07 12:09:59 +020031/**
Carmelo Casconee3a7c742017-09-01 01:25:52 +020032 * Implementation of PacketProgrammable behaviour for P4Runtime.
Andrea Campanella378e21a2017-06-07 12:09:59 +020033 */
Carmelo Casconee5b28722018-06-22 17:28:28 +020034public class P4RuntimePacketProgrammable
35 extends AbstractP4RuntimeHandlerBehaviour
36 implements PacketProgrammable {
Carmelo Cascone59f57de2017-07-11 19:55:09 -040037
Andrea Campanella378e21a2017-06-07 12:09:59 +020038 @Override
39 public void emit(OutboundPacket packet) {
Frank Wangc672c982017-07-18 16:09:28 +080040
Carmelo Casconec32976e2019-04-08 14:50:52 -070041 if (!this.setupBehaviour("emit()")) {
Frank Wangc672c982017-07-18 16:09:28 +080042 return;
43 }
44
Carmelo Casconec2be50a2019-04-10 00:15:39 -070045 final PiPipelineInterpreter interpreter = getInterpreter(handler());
Ray Milkey74e59132018-01-17 15:24:52 -080046 if (interpreter == null) {
Carmelo Cascone158b8c42018-07-04 19:42:37 +020047 // Error logged by getInterpreter().
Frank Wangc672c982017-07-18 16:09:28 +080048 return;
49 }
50
Carmelo Cascone080969a2019-08-27 16:06:55 -070051 if (log.isTraceEnabled()) {
52 logPacketOut(packet);
53 }
54
Frank Wangc672c982017-07-18 16:09:28 +080055 try {
Carmelo Cascone080969a2019-08-27 16:06:55 -070056 interpreter.mapOutboundPacket(packet).forEach(
57 op -> client.packetOut(p4DeviceId, op, pipeconf));
Frank Wangc672c982017-07-18 16:09:28 +080058 } catch (PiPipelineInterpreter.PiInterpreterException e) {
Carmelo Casconee5b28722018-06-22 17:28:28 +020059 log.error("Unable to translate outbound packet for {} with pipeconf {}: {}",
60 deviceId, pipeconf.id(), e.getMessage());
Frank Wangc672c982017-07-18 16:09:28 +080061 }
Andrea Campanella378e21a2017-06-07 12:09:59 +020062 }
Carmelo Cascone080969a2019-08-27 16:06:55 -070063
64 private void logPacketOut(OutboundPacket packet) {
65 final EthType.EtherType etherType = getEtherType(packet.data());
66 final String outPorts = packet.treatment().immediate().stream()
67 .filter(i -> i.type().equals(OUTPUT))
68 .map(i -> Long.toString(((Instructions.OutputInstruction) i).port().toLong()))
69 .collect(Collectors.joining(","));
70 final String desc = outPorts.isBlank()
71 ? "treatment=" + packet.treatment().toString()
72 : "egress_ports=" + outPorts;
73 log.trace("Sending PACKET-OUT >>> device={} {} eth_type={}",
74 packet.sendThrough(), desc,
75 etherType.ethType().toString());
76 }
77
78 private EthType.EtherType getEtherType(ByteBuffer data) {
79 final short shortEthType = data.getShort(12);
80 data.rewind();
81 return EthType.EtherType.lookup(shortEthType);
82 }
Andrea Campanella378e21a2017-06-07 12:09:59 +020083}